/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-07-06 09:18:46
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-07-06 10:28:54
 * @FilePath: /lesson/lesson_net/blog_cal_http/ServerMain.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "Protocol.hpp"
using namespace std;

void *Routine(void *arg)
{
    // 分离线程
    pthread_detach(pthread_self());

    int sock = *(int *)arg;
    delete (int *)arg;

    while (true)
    {
        request_t rq;
        ssize_t size = recv(sock, &rq, sizeof(rq), 0);
        if (size > 0)
        {
            response_t rp = {0, 0};
            switch (rq.op)
            {
            case '+':
                rp.result = rq.x + rq.y;
                break;
            case '-':
                rp.result = rq.x - rq.y;
                break;
            case '*':
                rp.result = rq.x * rq.y;
                break;
            case '/':
                if (rq.y == 0)
                {
                    rp.code = 1; // 除0错误
                }
                else
                {
                    rp.result = rq.x / rq.y;
                }
                break;
            case '%':
                if (rq.y == 0)
                {
                    rp.code = 2; // 模0错误
                }
                else
                {
                    rp.result = rq.x % rq.y;
                }
                break;
            default:
                rp.code = 3; // 非法运算
                break;
            }
            send(sock, &rp, sizeof(rp), 0);
        }
        else if (size == 0)
        {
            cout << "service done" << endl;
            break;
        }
        else
        {
            cerr << "read error" << endl;
            break;
        }
    }
    close(sock);
    return nullptr;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cout << "Usage" << argv[0] << "port" << endl;
        exit(-1);
    }

    int port = atoi(argv[1]);

    // 1、创建：监听套接字
    int listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sockfd < 0)
    {
        cerr << "create fail!" << endl;
        exit(-2);
    }

    // 2、bind：监听套接字
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));

    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(listen_sockfd, (struct sockaddr *)&local, sizeof(local)) < 0)
    {
        cerr << "bind fail" << endl;
    }

    // 3、监听套接字
    if (listen(listen_sockfd, 5) < 0)
    {
        cerr << "listen fail" << endl;
    }

    // 4、启动服务器

    struct sockaddr_in peer;
    memset(&peer, 0, sizeof(peer));

    while (true)
    {
        socklen_t len = sizeof(peer);
        int sockfd = accept(listen_sockfd, (struct sockaddr *)&peer, &len);
        if (sockfd < 0)
        {
            cerr << "accept fail" << endl;
            continue;
        }

        pthread_t tid = 0;

        int *p = new int(sockfd);
        pthread_create(&tid, nullptr, Routine, p);
    }

    return 0;
}
